#include "transFile.h"


void* puts_c(void *arg, MYSQL *conn){
    printf("this is puts.\n");
    
    Para *para = (Para *)arg;
    MYSQL *mysql = conn;
    char flag;
    char prefix[100] = "./file";
    TLV tlv;

    // 接收哈希值
    recv_tlv(para->netfd, &tlv);
    char hash_val[100] = {0};
    memcpy(hash_val, tlv.data, tlv.len);
    printf("hash:%s\n", hash_val);

    // 拿文件名
    char file_name[1024] = {0};
    char get_path[1024] = {0};
    memcpy(get_path, para->path[0], strlen(para->path[0]));
    char *p = strtok(get_path, "/");
    while(1){
        bzero(file_name, sizeof(file_name));
        strcpy(file_name, p);
        p = strtok(NULL, "/");
        if(p == NULL){
            break;
        }
    }
    printf("文件名：%s\n", file_name);

    char sql[1024] = {0};
    sprintf(sql, "select file_name from vfs where hash_val = '%s';", hash_val);
    mysql_query(mysql,sql);
    MYSQL_RES* res = mysql_store_result(mysql);
    MYSQL_ROW row;

    if(mysql_num_rows(res) > 0){ // 已经存在了，秒传
        flag = 'F';
        send_tlv(para->netfd, &flag, 1);
        printf("秒传成功.\n");
        return NULL;
    }

    bzero(sql, sizeof(sql));
    sprintf(sql, "select hash_val from vfs where file_name = '%s';", file_name);
    mysql_query(mysql,sql);
    res = mysql_store_result(mysql);
    printf("是否存在该文件名：%ld\n", mysql_num_rows(res));
    if(mysql_num_rows(res) > 0){ // 文件名存在但哈希值不同，断点续传
        row = mysql_fetch_row(res);
        flag = 'R';
        printf("flag:%c\n", flag);
        send_tlv(para->netfd, &flag, 1);

        // 组合路径
        char real_path[1024] = {0};
        sprintf(real_path,"%s/%s", prefix, hash_val);
        /* printf("%s\n", flag); */
        int fd = open(real_path, O_RDWR | O_APPEND);

        // 传当前文件大小
        struct stat file_stat;
        fstat(fd, &file_stat);
        off_t existing_size = file_stat.st_size;
        send_tlv(para->netfd, &existing_size, sizeof(existing_size));

        // 收剩余文件大小
        recv_tlv(para->netfd, &tlv);
        off_t remaining_size = 0;
        memcpy(&remaining_size, tlv.data, tlv.len);

        if(remaining_size < MAX_SIZE){
            while(remaining_size > 0){
                recv_tlv(para->netfd, &tlv);
                write(fd, tlv.data, tlv.len);
                remaining_size -= tlv.len;
            }
        }else{
            ftruncate(fd, existing_size + remaining_size);
            char *mp = (char *)mmap(NULL, remaining_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, existing_size);
            recv(para->netfd, mp, remaining_size, MSG_WAITALL);
            munmap(mp, remaining_size);
        }

        // 通过文件名更新hash_val
        char sql[1024] = {0};
        sprintf(sql, "upadte vfs set hash_val = '%s' where file_name = '%s';", hash_val, file_name);
        mysql_query(mysql, sql);
        res = mysql_store_result(mysql);

        return NULL;
    }else{
        //新文件上传
        flag = 'N';
        send_tlv(para->netfd, &flag, 1);
        printf("flag:%c\n", flag);

        // 组合路径
        char real_path[1024] = {0};
        sprintf(real_path,"%s/%s", prefix, hash_val);
        /* printf("%s\n", flag); */
        int fd = open(real_path, O_RDWR | O_CREAT | O_TRUNC, 0777);

        recv_tlv(para->netfd, &tlv);
        off_t file_size = 0;
        memcpy(&file_size, tlv.data, tlv.len);
        printf("文件大小:%ld\n", file_size);
        printf("%d\n", file_size < MAX_SIZE);

        if(file_size < MAX_SIZE){ // 小文件传输
            while(1){
                recv_tlv(para->netfd, &tlv);
                if(tlv.len == 0){
                    break;
                }
                printf("write before\n");
                write(fd, tlv.data, tlv.len);
                printf("write after\n");
            }
            close(fd);
        }
        else{ // 大文件传输
            char *mp = (char *)mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
            recv(para->netfd, mp, file_size, MSG_WAITALL);
            munmap(mp, file_size);
        }

        // 新插入数据
        /* int user_id = 0; */
        /* char sql[1024] = {0}; */
        /* sprintf(sql, "select user_id from vfs where user_name = '%s';", para->client->user_name); */
        /* mysql_query(mysql, sql); */
        /* res = mysql_store_result(mysql); */
        /* row = mysql_fetch_row(res); */
        /* memcpy(&user_id, row[0], strlen(row[0])); */

        /* char mysql_file_path[1024] = {0}; */
        /* deal_path(para->path[0], mysql_file_path); */


        /* bzero(sql, sizeof(sql)); */
        /* sprintf(sql, "INSERT INTO vfs (file_name, parent_id, hash_val, file_type, user_id, file_size, file_path) VALUES ('%s', %d, '%s', 'f', %d, %d, '%s');", */
        /*         file_name, 1, hash_val, user_id, file_size, mysql_file_path); */
        /* mysql_query(mysql,sql); */

    }
    return NULL;

}

void* gets_c(void *arg, MYSQL *conn){
    Para *para = (Para *)arg;
    MYSQL *mysql = conn;
    TLV tlv;
    MYSQL_RES *res;
    MYSQL_ROW row;
    char prefix[100] = "./file";

    char desire_file_name[1024] = {0};
    char get_path[1024] = {0};
    memcpy(get_path, para->path[0], strlen(para->path[0]));
    char *p = strtok(get_path, "/");
    while(1){
        bzero(desire_file_name, sizeof(desire_file_name));
        strcpy(desire_file_name, p);
        p = strtok(NULL, "/");
        if(p == NULL){
            break;
        }
    }

    char sql[1024] = {0};
    sprintf(sql, "select hash_val,file_size from vfs where file_name = '%s';", desire_file_name);
    mysql_query(mysql, sql);
    res = mysql_store_result(mysql);

    if(mysql_num_rows(res) <= 0){
        char error_message[1024] = "this file is not exit.";
        send_tlv(para->netfd, error_message, strlen(error_message));
        fprintf(stderr,"%s is not exit.\n", desire_file_name);
        return NULL;
    }

    // 真实路径拼接
    char real_path[1024] = {0};
    row = mysql_fetch_row(res);
    sprintf(real_path, "%s/%s", prefix, row[0]);
    printf("%s\n", real_path);


    off_t db_size = 0;
    memcpy(&db_size, row[1], strlen(row[1])); //原文件大小

    off_t offset = 0; // 接收客户端已经存在的大小
    recv_tlv(para->netfd, &tlv);
    memcpy(&offset, tlv.data, tlv.len);
    printf("%ld\n", offset);

    // 发送剩余文件大小
    off_t remaining_size = db_size - offset;
    printf("remain:%ld", remaining_size);
    send_tlv(para->netfd, &remaining_size, sizeof(remaining_size));
    tlv.len = sizeof(db_size);
    memcpy(tlv.data, &db_size, tlv.len);
    send(para->netfd, &tlv, sizeof(tlv.len) + tlv.len, MSG_NOSIGNAL);

    int fd = open(real_path, O_RDONLY);
    if(db_size < MAX_SIZE){
        while(1){
            char buffer[4096] = {0};
            ssize_t read_num = read(fd, buffer, sizeof(buffer));
            send_tlv(para->netfd, buffer, read_num);
            if(read_num == 0){
                break;
            }
        }

    }else{
        char *mp = (char *)mmap(NULL, db_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        send(para->netfd, mp, db_size, MSG_NOSIGNAL);
        munmap(mp, db_size);
    }



    return NULL;
}

